using NBehave.Spec.MbUnit;
using Pentago.Core;
using Rhino.Mocks;
using Context = MbUnit.Framework.TestFixtureAttribute;
using Specification = MbUnit.Framework.TestAttribute;

namespace Pentago.Specifications
{
    [Context]
    public class GameMasterSpecifications : SpecBase
    {
        // other possible formats - 1
//        [Specification]
//        public void Should_select_marble_colour_when_starting_new_game()
//        {
//            IPlayerSelect0r select0r = null;
//            IOut output = null;
//            GameMaster gameMaster = null;
//
//            Given(() =>
//                      {
//                          select0r = CreateDependency<IPlayerSelect0r>();
//                          output = CreateDependency<IOut>();
//                          gameMaster = new GameMaster(select0r, output, null, null);
//
//                          select0r.Expect(x => x.Select()).Return(Marble.White);
//                      });
//
//            When(() => gameMaster.SetupNewGame());
//
//            Then(() =>
//                     {
//                         output.ShouldBeToldTo(x => x.Write("White will start."));
//                         select0r.VerifyAllExpectations();
//                     });
//        }

        // other possible formats - 2
//        IPlayerSelect0r select0r = null;
//        IOut output = null;
//        GameMaster gameMaster = null;
//
//        protected override void EstablishContext()
//        {
//            base.EstablishContext();
//
//            select0r = CreateDependency<IPlayerSelect0r>();
//            output = CreateDependency<IOut>();
//            gameMaster = new GameMaster(select0r, output, null, null);
//
//            select0r.Expect(x => x.Select()).Return(Marble.White);
//        }
//
//        protected override void When()
//        {
//            gameMaster.SetupNewGame();
//        }
//
//        [Observation]
//        public void Should_select_marble_colour()
//        {
//            output.ShouldBeToldTo(x => x.Write("White will start."));
//            select0r.VerifyAllExpectations();
//        }


        [Specification]
        public void Should_select_marble_colour_when_starting_new_game()
        {
            var select0r = CreateDependency<IPlayerSelect0r>();
            var output = CreateDependency<IOut>();
            var gameMaster = new GameMaster(select0r, output, null, null);

            select0r.Expect(x => x.Select()).Return(Marble.White);

            gameMaster.SetupNewGame();

            output.ShouldBeToldTo(x => x.Write("White will start."));
            select0r.VerifyAllExpectations();
        }

        [Specification]
        public void Should_stop_when_player_wants_to_quit()
        {
            var select0r = CreateStub<IPlayerSelect0r>();
            var output = CreateStub<IOut>();
            var input = CreateDependency<IIn>();
            var gameBoard = CreateDependency<IGameBoard>();
            var gameMaster = new GameMaster(select0r, output, input, gameBoard);

            select0r.Stub(x => x.Select()).Return(Marble.White);
            gameMaster.SetupNewGame();

            input.Stub(x => x.Read()).Return("quit");

            gameMaster.Start();

            output.ShouldBeToldTo(x => x.Write("Stopping."));
        }

        [Specification]
        public void Should_prompt_the_first_player_for_position_place()
        {
            var select0r = CreateStub<IPlayerSelect0r>();
            var output = CreateStub<IOut>();
            var input = CreateStub<IIn>();
            var gameBoard = CreateDependency<IGameBoard>();
            var gameMaster = new GameMaster(select0r, output, input, gameBoard);

            select0r.Stub(x => x.Select()).Return(Marble.White);
            gameMaster.SetupNewGame();

            input.Stub(x => x.Read()).Return("1/1");
            input.Stub(x => x.Read()).Return("1/cw");
            input.Stub(x => x.Read()).Return("quit");

            gameMaster.Start();

            output.ShouldBeToldTo(x => x.Write("White, please enter new position: (block/location)"));
            gameBoard.ShouldBeToldTo(x => x.PlaceMarble(1, 1, Marble.White));

            output.ShouldBeToldTo(x => x.Write("White, please enter the block to twist with direction: (block/[cw|ccw])"));
            gameBoard.ShouldBeToldTo(x => x.TwistBlock(1, Direction.Clockwise));
        }

        [Specification]
        public void Should_prompt_the_second_player_once_the_first_player_has_played()
        {
            var select0r = CreateStub<IPlayerSelect0r>();
            var output = CreateStub<IOut>();
            var input = CreateStub<IIn>();
            var gameBoard = CreateStub<IGameBoard>();
            var gameMaster = new GameMaster(select0r, output, input, gameBoard);

            select0r.Stub(x => x.Select()).Return(Marble.White);
            gameMaster.SetupNewGame();

            input.Stub(x => x.Read()).Return("1/1");
            input.Stub(x => x.Read()).Return("1/cw");
            input.Stub(x => x.Read()).Return("1/2");
            input.Stub(x => x.Read()).Return("1/cw");
            input.Stub(x => x.Read()).Return("quit");

            gameMaster.Start();

            output.ShouldBeToldTo(x => x.Write("Black, please enter new position: (block/location)"));
            gameBoard.ShouldBeToldTo(x => x.PlaceMarble(1, 2, Marble.Black));
        }

        // add something to check if the game is over
    }
}